package org.Shiikong_Memory.SakuraBlockFrame.Builder;

import org.Shiikong_Memory.SakuraBlockFrame.Abnormal.NoInitAbnomal;
import org.bukkit.Bukkit;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.NamespacedKey;
import org.bukkit.plugin.Plugin;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;

import java.util.*;
import java.util.function.Consumer;

/**
 * GUI构建器
 * 该类用于方便地创建和配置自定义的库存界面（GUI），支持设置标题、尺寸、添加物品、
 * 注册点击和关闭事件等功能。
 * @author Shiikong_Memory
 * @version 1.0
 */
public class GUIBuilder {
    private static boolean isInit = false;
    private static Plugin plugin;
    private static NamespacedKey key;
    private static final Map<UUID, Consumer<InventoryCloseEvent>> CALLBACK_MAP = new HashMap<>();
    private static final WeakHashMap<Inventory, UUID> OPENING_INVENTORIES = new WeakHashMap<>();
    private static final Map<UUID, Map<Integer, Consumer<InventoryClickEvent>>> CLICK_CALLBACKS = new HashMap<>();
    private static final Map<UUID, Set<Integer>> DENIED_SLOTS = new HashMap<>();
    private static final WeakHashMap<Inventory, Boolean> BUILT_INVENTORIES = new WeakHashMap<>();

    private String title;
    private InventoryType inventoryType;
    private int size;
    private final ItemStack[] contents = new ItemStack[54];
    private UUID callbackId;
    private Consumer<InventoryCloseEvent> closeHandler;
    private final Map<Integer, Consumer<InventoryClickEvent>> clickHandlers = new HashMap<>();
    private final Set<Integer> deniedSlots = new HashSet<>();

    /**
     * 初始化GUI构建器
     * @param plugin 插件实例
     * @param keyName 命名空间键名
     */
    public static void init(Plugin plugin, String keyName) {
        GUIBuilder.plugin = plugin;
        key = new NamespacedKey(plugin, keyName);
        plugin.getServer().getPluginManager().registerEvents(new GUIListener(), plugin);
        isInit = true;
    }

    /**
     * 创建指定类型的GUI构建器
     * @param type 要创建的库存类型
     * @return 新构建器实例
     */
    public static GUIBuilder create(InventoryType type) {
        if (!isInit)throw new NoInitAbnomal("GUI构建器");
        GUIBuilder builder = new GUIBuilder();
        builder.inventoryType = type;
        builder.size = type.getDefaultSize(); // 从类型获取默认大小
        return builder;
    }

    /**
     * 设置GUI标题
     * @param title 要显示的标题文本
     * @return 当前构建器实例
     */
    public GUIBuilder title(String title) {
        this.title = title;
        return this;
    }

    /**
     * 配置GUI尺寸
     * @param size 目标尺寸（自动适配容器类型限制）
     * @return 当前构建器实例
     */
    public GUIBuilder size(int size) {
        // 根据不同类型设置有效范围（示例为箱子类容器）
        if (inventoryType == InventoryType.CHEST || inventoryType == InventoryType.ENDER_CHEST) {
            this.size = Math.min(54, Math.max(9, size / 9 * 9)); // 保持9的倍数
        } else {
            this.size = Math.min(54, Math.max(inventoryType.getDefaultSize(), size));
        }
        return this;
    }


    /**
     * 添加物品到指定位置
     * @param slot 组件所在的槽位
     * @param item 要添加的物品
     * @return 当前构建器实例
     */
    public GUIBuilder addComponent(int slot, ItemStack item) {
        if (slot >= 0 && slot < contents.length) {
            contents[slot] = item;
        }
        return this;
    }

    /**
     * 添加物品到指定位置
     * @param slots 组件所在的槽位
     * @return 当前构建器实例
     */
    public GUIBuilder denyClick(int... slots) {
        for (int slot : slots) {
            if (slot >= 0 && slot < this.size) {
                deniedSlots.add(slot);
            }
        }
        return this;
    }

    /**
     * 注册关闭事件处理器
     * @param handler 关闭时执行的回调函数
     * @return 当前构建器实例
     */
    public GUIBuilder onClose(Consumer<InventoryCloseEvent> handler) {
        this.closeHandler = handler;
        return this;
    }

    /**
     * 构建并生成配置完成的GUI
     * @return 创建完成的库存对象
     */
    public GUIBuilder onClick(int slot, Consumer<InventoryClickEvent> handler) {
        if (slot >= 0 && slot < this.size) {
            clickHandlers.put(slot, handler);
        }
        return this;
    }

    /**
     * 构建并生成配置完成的GUI
     * @return 创建完成的库存对象
     */
    public Inventory build() {
        Inventory inv;
        if (size != inventoryType.getDefaultSize()) {
            inv = Bukkit.createInventory(null, size, title); // 覆盖自定义大小
        }else{
            inv = Bukkit.createInventory(null, inventoryType, title);
        }
        inv.setContents(Arrays.copyOf(contents, size));
        if (closeHandler != null && plugin != null) {
            callbackId = UUID.randomUUID();
            // 改用预注册机制
            OPENING_INVENTORIES.put(inv, callbackId);
            CALLBACK_MAP.put(callbackId, closeHandler);
            if (!clickHandlers.isEmpty()) {
                CLICK_CALLBACKS.put(callbackId, new HashMap<>(clickHandlers));
            }
        }
        return inv;
    }

    public static boolean isViewingGUIBuilder(HumanEntity player) {
        if (player == null) return false;
        Inventory topInventory = player.getOpenInventory().getTopInventory();
        return BUILT_INVENTORIES.containsKey(topInventory);
    }

    // 保留原来的Inventory查询方法
    public static boolean isGUIBuilderInventory(Inventory inv) {
        return BUILT_INVENTORIES.containsKey(inv);
    }

    // 添加静态事件监听类
    private static class GUIListener implements Listener {
        // 添加打开事件监听
        @EventHandler
        public void onInventoryOpen(InventoryOpenEvent event) {
            Inventory inv = event.getInventory();
            UUID callbackId = OPENING_INVENTORIES.get(inv);
            if (callbackId != null) {
                event.getPlayer().getPersistentDataContainer().set(
                        key, PersistentDataType.STRING, callbackId.toString()
                );
                OPENING_INVENTORIES.remove(inv); // 仅需存储一次
            }
        }

        @EventHandler
        public void onInventoryClose(InventoryCloseEvent event) {
            Inventory inv = event.getInventory();
            BUILT_INVENTORIES.remove(inv);
            PersistentDataContainer pdc = event.getPlayer().getPersistentDataContainer();
            if (pdc.has(key, PersistentDataType.STRING)) {
                UUID callbackId = UUID.fromString(pdc.get(key, PersistentDataType.STRING));
                Consumer<InventoryCloseEvent> handler = CALLBACK_MAP.get(callbackId);
                if (handler != null) {
                    handler.accept(event);
                    CALLBACK_MAP.remove(callbackId); // 单次回调后移除
                }
                pdc.remove(key); // 清理玩家数据
            }
        }

        @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
            HumanEntity player = event.getWhoClicked();
            PersistentDataContainer pdc = player.getPersistentDataContainer();

            if (pdc.has(key, PersistentDataType.STRING)) {
                // 只处理当前GUI的点击
                if (event.getInventory().equals(event.getClickedInventory())) {
                    UUID callbackId = UUID.fromString(pdc.get(key, PersistentDataType.STRING));
                    Map<Integer, Consumer<InventoryClickEvent>> handlers = CLICK_CALLBACKS.get(callbackId);
                    Set<Integer> denied = DENIED_SLOTS.get(callbackId);
                    if (denied != null && denied.contains(event.getSlot())) {
                        event.setCancelled(true);
                        return;
                    }
                    if (handlers != null) {
                        Consumer<InventoryClickEvent> handler = handlers.get(event.getSlot());
                        if (handler != null) {
                            handler.accept(event);
                            event.setCancelled(true); // 默认取消物品移动
                        }
                    }

                }
            }
        }
    }
}